#ifndef __INSN_H__
#define __INSN_H__

#include <hbird_sdk_soc.h>

#define  ROW_LEN    3
#define  COL_LEN    3

////////////////////////////////////////////////////////////
// custom3:
// Supported format: only R type here
// Supported instr:
//  1. custom3 lbuf: load data(in memory) to row_buf
//     lbuf (a1)
//     .insn r opcode, func3, func7, rd, rs1, rs2    
//  2. custom3 sbuf: store data(in row_buf) to memory
//     sbuf (a1)
//     .insn r opcode, func3, func7, rd, rs1, rs2    
//  3. custom3 acc rowsum: load data from memory(@a1), accumulate row datas and write back 
//     rowsum rd, a1, x0
//     .insn r opcode, func3, func7, rd, rs1, rs2    
////////////////////////////////////////////////////////////

// custom lbuf 
//__STATIC_FORCEINLINE void custom_lbuf(int addr)
//{
//    int zero = 0;
//
//    asm volatile (
//       ".insn r 0x7b, 2, 1, x0, %1, x0"
//           :"=r"(zero)
//           :"r"(addr)
//     );
//}
//
//// custom sbuf
//__STATIC_FORCEINLINE void custom_sbuf(int addr)
//{
//    int zero = 0;
//
//    asm volatile (
//       ".insn r 0x7b, 2, 2, x0, %1, x0"
//           :"=r"(zero)
//           :"r"(addr)
//     );
//}
//
//
//// custom rowsum
//__STATIC_FORCEINLINE int custom_rowsum(int addr)
//{
//    int rowsum;
//
//    asm volatile (
//       ".insn r 0x7b, 6, 6, %0, %1, x0"
//             :"=r"(rowsum)
//             :"r"(addr)
//     );
//
//    return rowsum;
//}
///////////////////////////////////////////////////////LOAD////////////////////////////////////////////////
//opcode, func3, func7, rd, rs1, rs2

//func7=0 		0 		0 	001		0
//		LOAD 	RAM1 		4行 		64位
//加载随机数d 64*4 位置{3'b100, 9 ,2'b0} RAM1
__STATIC_FORCEINLINE void custom_kyber_load_d(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b0000010, x9, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}

//加载随机数d 64*4 位置{3'b100, 0 ,2'b0} RAM1
__STATIC_FORCEINLINE void custom_kyber_load_d_1024(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b0000010, x0, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}
//func7=0 		0 		0 	001		0
//		LOAD 	RAM1 		4行 		64位
//加载明文m 64*4 位置{3'b100, 0 ,2'b0}
__STATIC_FORCEINLINE void custom_kyber_load_m(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b0000010, x0, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}

//func7=0 		0 		0 	001		0
//		LOAD 	RAM1 		4行 		64位
//加载随机数ρ 64*4 位置{3'b100, 9 ,2'b0}
__STATIC_FORCEINLINE void custom_kyber_load_rou(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b0000010, x9, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}
__STATIC_FORCEINLINE void custom_kyber_load_rou_1024(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b0000010, x1, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}
//func7=0 		0 		0 	011		1
//		LOAD 	RAM1 		64行 	96位
//加载Kyber512公钥t0和t1 96*32*2 位置{ 10 ,5'b0}
__STATIC_FORCEINLINE void custom_kyber_load_t_512(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b0000111, x10, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}
//func7=0 		0 		0 	101		1
//		LOAD 	RAM1 		128行 	96位
//加载Kyber512公钥t0和t1和t2和t3 96*32*4 位置{ 4 ,5'b0}
__STATIC_FORCEINLINE void custom_kyber_load_t_1024(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b0001011, x4, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}
//func7=0 		0 		0 	011		1
//		LOAD 	RAM1 		64行 	96位
//加载Kyber512密钥s0和s1 96*32*2 位置{ 8 ,5'b0}
__STATIC_FORCEINLINE void custom_kyber_load_s_512(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b0000111, x8, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}
//func7=0 		0 		0 	101		1
//		LOAD 	RAM1 		128行 	96位
//加载Kyber1024密钥s0和s1和s2和s3 96*32*4 位置{ 0 ,5'b0}
__STATIC_FORCEINLINE void custom_kyber_load_s_1024(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b0001011, x0, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}
//func7=0 		1 		0 	011		1
//		LOAD 	RAM2 		64行 	96位
//加载Kyber512压缩后密文u0和u1 96*32*2  位置{ 0 ,5'b0}
__STATIC_FORCEINLINE void custom_kyber_load_u_512(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b0100111, x0, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}
//func7=0 		1 		0 	101		1
//		LOAD 	RAM2 		128行 	96位
//加载Kyber1024压缩后密文u0和u1和u2和u3 96*32*4  位置{ 0 ,5'b0}
__STATIC_FORCEINLINE void custom_kyber_load_u_1024(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b0101011, x0, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}

//func7=0 		1 		0 	010		1
//		LOAD 	RAM2 		32行 	96位
//加载Kyber512压缩后密文v 96*32 位置{ 2 ,5'b0}
__STATIC_FORCEINLINE void custom_kyber_load_v_512(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b0100101, x2, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}

//func7=0 		1 		0 	010		1
//		LOAD 	RAM2 		32行 	96位
//加载Kyber1024压缩后密文v 96*32 位置{ 4 ,5'b0}
__STATIC_FORCEINLINE void custom_kyber_load_v_1024(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b0100101, x4, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}
///////////////////////////////////////////////////////STORE////////////////////////////////////////////////
//func7=1 		1 		0 	001		0
//		STORE 	RAM2 		4行 		64位
//存储明文m 64*4 位置{3'b100, 0 ,2'b0} RAM2
__STATIC_FORCEINLINE void custom_kyber_store_m(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b1100010, x0, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}

//func7=1 		0 		0 	001		0
//		STORE 	RAM1 		4行 		64位
//存储Share K 64*4 位置{3'b100, 4 ,2'b0} RAM1
__STATIC_FORCEINLINE void custom_kyber_store_k(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b1000010, x4, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}

//func7=1 		0 		0 	001		0
//		STORE 	RAM1 		4行 		64位
//存储rou 64*4 位置{3'b100, 9 ,2'b0} RAM1
__STATIC_FORCEINLINE void custom_kyber_store_rou(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b1000010, x9, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}

//存储rou 64*4 位置{3'b100, 1 ,2'b0} RAM1
__STATIC_FORCEINLINE void custom_kyber_store_rou_1024(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b1000010, x1, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}
//func7=1 		1 		0 	011		1
//		STORE 	RAM2 		64行 	96位
//func7=1000010
//存储Kyber512公钥t0和t1 96*32*2 位置{ 6 ,5'b0}
__STATIC_FORCEINLINE void custom_kyber_store_t_512(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b1100111, x6, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}
//func7=1 		1 		0 	101		1
//		STORE 	RAM2 		128行 	96位
//存储Kyber1024公钥t0和t1和t2和t3 96*32*4 位置{ 4 ,5'b0}
__STATIC_FORCEINLINE void custom_kyber_store_t_1024(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b1101011, x4, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}

//func7=1 		1 		0 	011		1
//		STORE 	RAM2 		64行 	96位
//存储Kyber512密钥s0和s1 96*32*2 位置{ 0 ,5'b0}
__STATIC_FORCEINLINE void custom_kyber_store_s_512(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b1100111, x0, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}
//func7=1 		1 		0 	101		1
//		STORE 	RAM2 		128行 	96位
//存储Kyber1024密钥s0和s1和s2和s3 96*32*4 位置{ 0 ,5'b0}
__STATIC_FORCEINLINE void custom_kyber_store_s_1024(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b1101011, x0, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}

//func7=1 		1 		0 	011		1
//		STORE 	RAM2 		64行 	96位
//存储Kyber512压缩后密文u0和u1 96*32*2 位置{ 3 ,5'b0}
__STATIC_FORCEINLINE void custom_kyber_store_u_512(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b1100111, x3, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}
//func7=1 		1 		0 	101		1
//		STORE 	RAM2 		128行 	96位
//存储Kyber1024压缩后密文u0和u1和u2和u3 96*32*4 位置{ 0 ,5'b0}
__STATIC_FORCEINLINE void custom_kyber_store_u_1024(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b1101011, x0, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}

//func7=1 		1 		0 	010		1
//		STORE 	RAM2 		32行 	96位
//存储Kyber512压缩后密文v 96*32 位置{ 5 ,5'b0}
__STATIC_FORCEINLINE void custom_kyber_store_v_512(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b1100101, x5, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}
//		STORE 	RAM2 		32行 	96位
//存储Kyber1024压缩后密文v 96*32 位置{ 4 ,5'b0}
__STATIC_FORCEINLINE void custom_kyber_store_v_1024(int addr)
{

	int zero = 0;

    asm volatile (
       ".insn r 0x7b, 2, 0b1100101, x4, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );
}

//__STATIC_FORCEINLINE void test(int a, int b)
//{
//	int zero = 0;
//    asm volatile (
//       ".insn r 0x7b, 0, 0b1100101, x0, %1, %2"
//           :"=r"(zero)
//           :"half"(a), "half"(b)
//     );
//}
// normal test case without NICE accelerator.
int normal_case(unsigned int array[ROW_LEN][COL_LEN]);

// teat case using NICE accelerator.
//int nice_case(unsigned int array[ROW_LEN][COL_LEN]);
void nice_case(unsigned int message[]);

#endif

